\documentclass[a4paper,twoside,12pt]{article}
\usepackage[MeX]{polski}
\usepackage[utf8]{inputenc}
\usepackage{indentfirst,graphicx,amsmath}
\usepackage[left=3cm,top=2cm,right=3cm,nohead]{geometry}
\frenchspacing

\pagestyle{plain}
\author{Sławomir Nowaczewski, Bartosz Pastudzki, Mariusz Redwanz}
\title{System emulacji bezprzewodowej sieci komputerowej}
\newcommand{\byauth}[1]{\vspace{-10pt}{\bf\noindent\footnotesize (#1)}\par}
\begin{document}

\tableofcontents

\newpage

\section{Wstęp}
    W ramach projektu tworzony będzie system emulujący działanie
    ,,wielokomórkowej” radiowej sieci LAN. Zgodnie z przyjętymi wcześniej
    założeniami do realizacji projektu użyte zostaną karty sieciowe EDIMAX
    EU-4207. Jest to adapter USB 2.0 z Fast Ethernet, do którego dostarczone
    jest otwarte oprogramowanie współpracujące z jądrem Linuxa.

    \subsection{Cechy sterownika karty USB}
    \byauth{Bartosz Pastudzki}
        Nasza karta sieciowa komunikuje się z komputerem za pośrednictwem portu
        USB. W związku z tym w kodzie często pojawia się struktura {\tt usbnet}
        przechowująca najważniejsze informacje na temat urządzenia.
           
        Inną cechą charakterystyczną jest struktura {\tt urb}\footnote{ USB
        Request Block. Więcej na stronie {\tt http://www.mjmwired.net/kernel/Documentation/usb/URB.txt}}
        służąca do wykonywania komend USB. Zawiera ona szczegóły wywoływanej
        komendy, która zostanie wykonana poprzez funkcję {\tt usb\_fill\_control\_urb()}.

        Dla porównania przeanalizowałem również sterownik karty {\tt SiS900}
        będącej kartą ethernetową PCI. Tam wszystkie funkcje sterownika
        korzystają z interfejsu  typowego dla kart PCI, będącego zestawem
        funkcji służących do różnych celów zamiast jednej funkcji, której
        działanie zależne jest od zawartości podanej struktury, jak to ma
        miejsce w przypadku USB.

        Z drugiej strony, w obu przypadkach główna funkcja sterownika rejestruje
        odpowiednio urządzenie PCI lub USB, a te przy inicjacji rejestrują
        urządzenie ethernetowe. Jednakże w obu przypadkach wygląda to trochę
        inaczej. Nasze urządzenie USB nie implementuje działania {\tt probe}
        lecz wykorzystuje standardową funkcję służącą do wykonywanie {\tt probe}
        dla kart sieciowych USB ({\tt usbnet\_probe}, która otrzymuje listę
        modeli powiązanych ze sterownikiem, wraz z zestawem funkcji je
        obsługujących. Natomiast sterownik wspomnianej karty PCI sam
        implementował taką funkcję.
        
        Taka rozbieżność jest to podyktowana strukturą jądra, gdyż sterownik
        {\tt iwlwifi} obsługujący wiele kart sieciowych PCI również sam
        implementuje funkcję {\tt probe}. Zatem prawdopodobnie w jądrze nie ma
        standardowej funkcji {\tt probe} dla kart sieciowych PCI. W praktyce
        oznacza to, że karta sieciowa USB zwykle implementuje 2 interfejsy,
        a karta PCI tylko jeden. W kodzie obiawia się to w ten sposób, że
        w karcie USB implementowane funkcje operują na strukturze {\tt usbnet}
        bądź {\tt net\_device}, a w karcie PCI tylko {\tt net\_device}.

    \subsection{Opis przykładowej zmiany sterownika asix.c}
    \byauth{Mariusz Redwanz}
        Wprowadzona przez nas zmiana polega na programowej zmianie adresu
        fizycznego karty sieciowej, tak aby niemożliwa była jego zmiana za
        pomocą np. ploecenia ifconfig. Poniżej znajduje się kod funkcji
        odpowiadajacej za ustawienie adresu fizycznego urządzenia: 
        \begin{verbatim}
static int ax8817x_set_mac_addr (struct net_device *net, void *p)
{
    struct usbnet *dev = netdev_priv(net);
    struct sockaddr *addr = p;
    memcpy (net->dev_addr, addr->sa_data, ETH_ALEN);
    return ax8817x_write_cmd (dev, AX88772_CMD_WRITE_NODE_ID, 0, 0,
                                ETH_ALEN, net->dev_addr);
}
        \end{verbatim}
        Do funkcji przekazywane są dwa parametry – wskaźnik na strukturę
        {\tt net\_device}, która zawiera najważniejsze informacje o urządzeniu
        oraz wskaźnik typu void. W pierwszej linii funkcji
        {\tt ax8817x\_set\_mac\_addr} prywatne dane urządzenia zostają pobrane
        za pomoca funkcji {\tt netdev\_priv} i wpisane do obiektu typu usbnet.
        W kolejnej linii do obiektu typu sockaddr wpisane zostają informacje
        o rodzinie adresów oraz adresie protokołu. W trzeciej linii adres MAC
        urządzenia zostaje skopiowany z pola {\tt sa\_data} do pola
        {\tt dev\_addr} w obiekcie net. W ostaniej linii wywoływana jest funkcja
        {\tt ax8817x\_write\_cmd}, która przekazuje komendę do wykonania.

        Aby {\it na sztywno} podać adres fizyczny karty sieciowej należy
        zaalokować bufor przechowujący ten adres oraz skopiować jego zawartość
        do pola {\tt dev\_addr} w obiekcie {\tt net\_device} (zamiast pola
        {\tt sa\_data} z obiektu {\tt dev\_addr}). Poniżej znajduje się kod
        z opisaną zmianą:

        \begin{verbatim}
static int ax8817x_set_mac_addr (struct net_device *net, void *p)
{
    struct usbnet *dev = netdev_priv(net);
    struct sockaddr *addr = p;
    void *buf;
    buf = kmalloc(6, GFP_KERNEL);
    ((char *)buf)[0] = 0x00;
    ((char *)buf)[1] = 0x50;
    ((char *)buf)[2] = 0xB6;
    ((char *)buf)[3] = 0x4E;
    ((char *)buf)[4] = 0x54;
    ((char *)buf)[5] = 0x9C;

    memcpy(net->dev_addr, buf, ETH_ALEN);
    return ax8817x_write_cmd (dev, AX88772_CMD_WRITE_NODE_ID, 0, 0,
                                ETH_ALEN, net->dev_addr);
}
        \end{verbatim}
\section{Implementacja}
    \subsection{Protokół komunikacji między kartami sieciowymi}
    \byauth{Bartosz Pastudzki}
        Naszym zadaniem jest emulacja sieci bezprzewodowej przy użyciu kart
        ethernetowych, które różnią się sposobem do medium. Zamiast unikać
        kolizji (CSMA/CA), w ethernecie się je wykrywa (CSMA/CD). Emulowanie
        sieci bezprzewodowej z CSMA/CD dawałoby niemiarodajne wyniki. Dlatego
        należy zasymulować dostęp do łącza typowy dla sieci bezprzewodowych.

        Niestety implementacja metody dostępu do łącza jest implementowany
        w samej karcie sieciowej, a nie w jej sterowniku bądź jądrze systemu.
        Z tego względu nie możemy go zmodyfikować. Dlatego zdecydowalśmy się
        zaprojektować taki protokół komunikacji między kartami sieciowymi żeby
        kolizje nie występowały.

        Postawową cechą takiego protokołu byłoby to, że w każdej chwili
        każdy uczesnik wymiany informacji (tj. sterownik karty sieciowej)
        wie kiedy powinien nadawać. Najprostszym sposobem uzyskania tego
        byłoby przydzielenie każdemu intefejsowi numeru i wysyłanie po
        jednej ramce po kolei (bądź ramce oznaczającej ,,nie mam nic do
        powiedzenia"). Dodatkowo każda ramka musiałaby być wzbogacona o czas
        nadania, tak aby na podstawie kilku ostatnich ramek dało się
        określić w jakiej kolejności i w jakich odstępach czasowych powinny
        zostać wysłane do odbiorców.

        Przyjmijmy, że sieć objemuje 4 wirtualne interfejsy rozmieszczone po
        2 na 2 węzłach sieci bezprzewodowej. Interfejsy numer 1, 3 i 4 chcę
        wysłać swoje ramki. Wymiana informacji na poziomie sterowników
        będzie wyglądać tak jak na rysunku~\ref{basiccomm}.

        \begin{figure}
            \includegraphics[width=0.7\paperwidth]{proto1.png}
            \caption{Komunikacja na poziomie sterowników.}
            \label{basiccomm}
        \end{figure}

        Każdy uczestnik wysyła po kolei informacje o tym co robią
        umieszczone na nim interfejsy. Dzięki temu nie ma ryzyka zajścia
        kolizji, bo każdy uczestnik wie kiedy jest jego kolej.

        Po każdej turze każdy z uczestników ma zestaw ramek, po jednej na
        interfejs i na tej podstawie symulator opisany w pkt. \ref{linksim}
        może odtworzyć kolejność w jakiej interfejsy chciały nadać ramki (rys.
        \ref{basiccomm2}) i na tej podstawie określić jak taka wymiana
        informacji wyglądałaby przy unikaniu kolizji. Wynik takiej symulacji
        przedstawia rys. \ref{basiccomm3}.

        \begin{figure}[]
            \center
            \includegraphics[width=0.6\paperwidth]{proto2.png}
            \caption{Komunikacja na poziomie logicznym}
            \label{basiccomm2}
        \end{figure}
        
        \begin{figure}[]
            \center
            \includegraphics[width=0.6\paperwidth]{proto3.png}
            \caption{Komunikacja na poziomie emulacji.}
            \label{basiccomm3}
        \end{figure}
    \subsection{Symulator dostępu do łacza}
        \label{linksim}
        Symulator będzie realizowany w tym samym wątku co reszta emulatora,
        a jego użycie jest zdefiniowane w pliku {\tt link.h}. Przed użyciem
        należy wywołać funkcję alokującą strukturę symulatora.

        Aby rozpocząć symulację należy wprowadzić po jednej ramce dla każdego
        interfejsu biorącego udział w symulacji wraz z czasem nadania. Bufor
        jest zaalokowany na stałe, więc dla każdego elementu tablicy
        {\tt frame\_buffer} wystarczy ustawić timestamp (czas nadania) i wpisać
        treść ramki do pola {\tt content}. Wartość timestamp $-1$ oznacza, że
        interfejs nie wysłał żadnej ramki w danej iteracji. Nie trzeba tego
        ustawiać ręcznie gdyż funkcja inicjująca i funkcja symulatora ustawiają
        wszystkie ramki na nienadane.

        Po wprowadzeniu ramek należy uruchomić funkcję {\tt link\_simulate}.
        Symulacja zostanie rozpoczęta {\tt SIM\_INTERVAL} nanosekund po
        rozpoczęciu poprzedniej. Jeśli upłynęło już więcej czasu, zostanie
        wygenerowane ostrzeżenie.

        Gdy chcemy skończyć symulację należy zwolnić pamięć przy pomocy funkcji
        {\tt end\_link\_sim}.
\end{document}
